package myJs.cps.project

import myJs.api.Api
import myJs.cps.BootstrapTableCp.Column
import myJs.cps.{BootstrapTableCp, Style}
import myJs.myPkg.reactBootstrap.{OverlayTrigger, Popover}
import myJs.tool.Pojo.{ExportData, NumericSearch, TextSearch}
import myJs.tool.Tool
import shared.tsPojo.TsPojo
import slinky.core.FunctionalComponent
import slinky.core.annotations.react
import slinky.core.facade.Hooks.{useEffect, useState}
import slinky.core.facade.ReactElement
import slinky.web.html._

import scala.collection.immutable.SeqMap
import scala.scalajs.js
import myJs.Implicits._
import org.scalajs.macrotaskexecutor.MacrotaskExecutor.Implicits._

/** Created by yz on 21/1/2022
  */
@react object GeneExpCp {

  case class Props(geneName: String, kind: String)

  val component = FunctionalComponent[Props] { props =>
    val phenotype = props.kind match {
      case "FibCs" => "Cirrhosis"
      case x => x
    }

    val (datas, setDatas) = useState(List.empty[ujson.Obj])
    val (columns, setColumns) = useState(List.empty[Column])

    useEffect(
      () => {
        FTool.refreshTableB()
      },
      List(props.geneName, props.kind)
    )

    object FTool {

      val map = SeqMap(
        "gene" -> "Gene",
        "lineage" -> "Lineage",
        "clusterResolution" -> "Resolution",
        "cellType" -> "Cell_Type",
        "suggestedLabels" -> "Suggested_Labels",
        "avgExp" -> "AvgExpr",
        "freq" -> "Freq"
      )

      def refreshTableB = () => {
        import TsPojo.browseGene._
        val request = GeneExp.Request(geneName = props.geneName, phenotype = phenotype)
        Api.browseGene.geneExp(request).map { tableRs =>
          val basicColumns = map.map { case (k, v) =>
            val searchKind = k match {
              case "avgExp" | "freq" => NumericSearch
              case _ => TextSearch
            }
            val fmt = FTool.tbFmt(k)
            val comVF = FTool.comVFmt(v)
            Column(field = k, title = v, operable = true, searchKind = searchKind, formatter = fmt, comVF = comVF)
          }.toList
          val curDatas = tableRs
          setColumns(basicColumns)
          setDatas(curDatas)
        }
      }

      def tbFmt(field: String) = (v: ujson.Value, row: ujson.Obj) => {
        field match {
          case "avgExp" =>
            span(v.str.onlyDoubleFixed(3))()
          case "freq" =>
            span(v.str.onlyDoubleFixed(3))()
          case _ => span(v.myStr)()
        }
      }

      def comVFmt(fileTitle: String) = (v: ujson.Value, row: ujson.Obj) => {
        fileTitle match {
          case _ => v.myStr
        }
      }

      def downloadData = () => {
        val headers = map.valueList
        val contents = datas.map { obj =>
          map.keyList.map { k =>
            obj.value(k).myStr
          }
        }
        val content = (headers :: contents).map(_.mkString("\t")).mkString("\n")
        Tool.downloadTxt(s"${props.geneName}.txt", content)
      }

    }

    val exportDatas = List(
      ExportData("TXT", onClick = FTool.downloadData)
    )

    div(
      h5(
        style := Style(marginBottom = 15, fontSize = 16, marginTop = 15),
        id := "exp",
        "Expression Statistics ", {
          val popover: ReactElement = Popover(id = "popover-basic")(
            Popover.Title("Note"),
            Popover.Content(
              "Average gene expression and percentage of cells expressing the given gene in each cluster"
            )
          )
          OverlayTrigger(
            placement = "right",
            trigger = js.Array("focus", "hover"),
            overlay = popover
          )(
            span(
              a(`type` := "button", i(className := "fas fa-info-circle"))
            )
          )
        }
      ),
      BootstrapTableCp(
        columns = columns,
        datas = datas,
        pageList = List(10, 25, 50),
        pageSize = 10,
        showExport = true,
        exportData = exportDatas,
        selectColumnEnabled = true,
        showColumnNames = List("Gene", "Lineage", "Resolution", "Cell_Type", "AvgExpr", "Freq")
      )
    )

  }

  object STool {}

}
